/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.saleorder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.xiaonuo.core.context.login.LoginContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.modular.pro.entity.Pro;
import vip.xiaonuo.modular.pro.service.ProService;
import vip.xiaonuo.modular.proplan.entity.ProPlan;
import vip.xiaonuo.modular.saleorder.entity.SaleOrder;
import vip.xiaonuo.modular.saleorder.enums.SaleOrderExceptionEnum;
import vip.xiaonuo.modular.saleorder.mapper.SaleOrderMapper;
import vip.xiaonuo.modular.saleorder.param.SaleOrderParam;
import vip.xiaonuo.modular.saleorder.result.SaleOrderResult;
import vip.xiaonuo.modular.saleorder.service.SaleOrderService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.modular.task.entity.Task;
import vip.xiaonuo.modular.task.enums.TaskStatusEnum;
import vip.xiaonuo.modular.task.mapper.TaskMapper;
import vip.xiaonuo.modular.task.service.TaskService;
import vip.xiaonuo.modular.workorder.entity.WorkOrder;
import vip.xiaonuo.modular.workorder.enums.WorkOrderStatusEnum;
import vip.xiaonuo.modular.workorder.enums.WorkOrderTypeEnum;
import vip.xiaonuo.modular.workorder.param.WorkOrderParam;
import vip.xiaonuo.modular.workorder.result.WorkOrderResult;
import vip.xiaonuo.modular.workorder.service.WorkOrderService;
import vip.xiaonuo.modular.workorderbill.entity.WorkOrderBill;
import vip.xiaonuo.modular.workorderbill.enums.WorkOrderBillEnum;
import vip.xiaonuo.modular.workorderbill.service.WorkOrderBillService;
import vip.xiaonuo.modular.workordertask.service.WorkOrderTaskService;
import vip.xiaonuo.modular.workreport.entity.WorkReport;
import vip.xiaonuo.modular.workreport.service.WorkReportService;
import vip.xiaonuo.modular.workroute.service.WorkRouteService;
import vip.xiaonuo.modular.workstep.entity.WorkStep;
import vip.xiaonuo.modular.workstep.service.WorkStepService;
import vip.xiaonuo.modular.worksteproute.entity.WorkStepRoute;
import vip.xiaonuo.modular.worksteproute.service.WorkStepRouteService;
import vip.xiaonuo.util.AutoCode;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 销售订单service接口实现类
 *
 * @author wyf
 * @date 2022-07-12 16:07:31
 */
@Service
public class SaleOrderServiceImpl extends ServiceImpl<SaleOrderMapper, SaleOrder> implements SaleOrderService {

    @Resource
    private WorkOrderService workOrderService;

    @Resource
    private WorkOrderBillService workOrderBillService;
    @Resource
    private WorkStepService workStepService;

    @Resource
    private ProService proService;

    @Resource
    private TaskService taskService;

    @Resource
    private WorkStepRouteService workStepRouteService;

    @Resource
    private WorkReportService workReportService;


    @Override
    public PageResult<SaleOrderResult> page(SaleOrderParam saleOrderParam) {
        QueryWrapper<SaleOrderResult> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(saleOrderParam)) {
            // 根据订单编号 查询
            if (ObjectUtil.isNotEmpty(saleOrderParam.getCode())) {
                queryWrapper.lambda().like(SaleOrder::getCode, saleOrderParam.getCode());
            }
            // 根据备注查询
            if (ObjectUtil.isNotEmpty(saleOrderParam.getRemarks())) {
                queryWrapper.lambda().like(SaleOrder::getRemarks, saleOrderParam.getRemarks());
            }
        }
        queryWrapper.orderByDesc("a.create_time");
        //进行二次数据处理
        //取到查到的数据
        Page<SaleOrderResult> page = this.baseMapper.page(PageFactory.defaultPage(), queryWrapper);
        /*
         * ===============================================处理数据的准备工作 start ======================================
         */

        //查询所有的销售订单保存至saleOrderMap
        Map<Long, SaleOrder> saleOrderMap = new HashMap<>();
        List<SaleOrder> saleOrderList = this.list();
        if (ObjectUtil.isNotEmpty(saleOrderList)) {
            saleOrderList.forEach(item -> saleOrderMap.put(item.getId(), item));
        }
        // 销售订单为 1
        // 先取到所有的关于生产计划的单据
        QueryWrapper<WorkOrderBill> billQueryWrapper = new QueryWrapper<>();
        billQueryWrapper.lambda().eq(WorkOrderBill::getType, WorkOrderBillEnum.SaleOrder.getCode());
        List<WorkOrderBill> billList = workOrderBillService.list(billQueryWrapper);
        // 设定一个Map key 为生产计划id,value 为 该生产计划ID的所有的单据
        Map<Long, List<WorkOrderBill>> billGroupByInvId = billList.stream().collect(Collectors.groupingBy(WorkOrderBill::getBillId));
        // 设定一个Map key 为工单id,value 为 该工单的所有任务
        QueryWrapper<Task> taskQueryWrapper = new QueryWrapper<>();
        taskQueryWrapper.lambda().orderByAsc(Task::getSortNum);
        List<Task> taskList = taskService.list(taskQueryWrapper);
        Map<Long, List<Task>> taskMap = taskList.stream().collect(Collectors.groupingBy(Task::getWorkOrderId));
        // 设定一个Map key 为单据id,value 为 工单
        List<WorkOrder> workOrderList = workOrderService.list();
        Map<Long, WorkOrder> workOrderMap = workOrderList.stream().collect(Collectors.toMap(WorkOrder::getBillId, a -> a, (k1, k2) -> k1));
        /*
         * ===============================================处理数据的准备工作 end ======================================
         */
        page.getRecords().forEach(item -> {
            // 记录结束工单数
            AtomicReference<Integer> endWorkerorderNum = new AtomicReference<>(0);
            Long id = item.getId();
            if (ObjectUtil.isEmpty(id)) {
                return;
            }
            List<WorkOrderResult> workOrders = new ArrayList<>();
            // 创建一个数组同来储存工单进度
            List<Integer> progressRateList = new ArrayList<>();
            //获得该条生产计划下的对应工单列表
            if (ObjectUtil.isNotNull(billGroupByInvId.get(item.getId()))) {
                billGroupByInvId.get(item.getId()).forEach(bill -> {
                    // workOrderMap 中获取工单id
                    WorkOrder workOrder = workOrderMap.get(bill.getId());
                    if(ObjectUtil.isNotNull(workOrder)){
                        if (WorkOrderStatusEnum.FINISH.getCode().equals(workOrder.getStatus())) {
                            endWorkerorderNum.set(endWorkerorderNum.get() + 1);
                        }
                        // 根据工单id查找任务
                        if (ObjectUtil.isNotNull(taskMap.get(workOrder.getId()))) {
                            taskMap.get(workOrder.getId()).forEach(task -> {
                                int progressRate = 0;
                                Integer plaNum = task.getPlaNum();
                                Integer goodNum = task.getGoodNum();
                                if (ObjectUtil.isNotEmpty(plaNum) && ObjectUtil.isNotEmpty(goodNum)) {
                                    progressRate = (100 * goodNum) / plaNum;
                                }
                                progressRateList.add(progressRate);
                            });
                        }
                        // 把工单任务进度放进 workOrderResult
                        WorkOrderResult workOrderResult = new WorkOrderResult();
                        BeanUtil.copyProperties(workOrder, workOrderResult);
                        workOrderResult.setProgressRateList(progressRateList);
                        workOrders.add(workOrderResult);
                    }

                });
            }

            if (ObjectUtil.isEmpty(workOrders)) {
                return;
            }
            item.setWorkOrderList(workOrders);
            item.setEndWorkerorderNum(endWorkerorderNum.get());
        });

        /*
         * ===============================================给入库明细list赋值 end ======================================
         */
        return new PageResult<>(page);
    }

    @Override
    public List<SaleOrder> list(SaleOrderParam saleOrderParam) {
        return this.list();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SaleOrderParam saleOrderParam) {
        //防止销售订单为空
        if (ObjectUtil.isEmpty(saleOrderParam.getWorkOrderList())) {
            throw new ServiceException(1, "工单不能为空");
        }
        checkParam(saleOrderParam, false);
        //如果编码为空，手动添加编码
        if (ObjectUtil.isEmpty(saleOrderParam.getCode())) {
            saleOrderParam.setCode(AutoCode.getCodeByService("dw_sale_order", this.getClass(), 0));
        }
        SaleOrder saleOrder = new SaleOrder();
        BeanUtil.copyProperties(saleOrderParam, saleOrder);
        this.save(saleOrder);
        List<WorkOrder> workOrderList = saleOrderParam.getWorkOrderList();
        addOrUpdateWrok(saleOrder, workOrderList, false);
    }

    private void addOrUpdateWrok(SaleOrder saleOrder, List<WorkOrder> workOrderList, boolean isExcludeSelf) {
        // 设置一个addWorkOrderList 为批量增加工单做准备
        List<WorkOrder> addWorkOrderList = new ArrayList<>();
        // 设置一个addWorkOrderBill 为批量增加工单做准备
        List<WorkOrderBill> addWorkOrderBillList = new ArrayList<>();
        // 开始添加的工单单据关系
        workOrderList.forEach(workOrder -> {
            WorkOrderBill workOrderBill = new WorkOrderBill();
            workOrderBill.setType(WorkOrderBillEnum.SaleOrder.getCode());
            workOrderBill.setProId(workOrder.getProId());
            workOrderBill.setBillId(saleOrder.getId());
            addWorkOrderBillList.add(workOrderBill);
            addWorkOrderList.add(workOrder);
        });
        // 批量添加 工单单据关系
        workOrderBillService.saveBatch(addWorkOrderBillList);
        // 工单编号使用
        String template = "{}-{}";
        AtomicReference<Integer> workOrderNumber = new AtomicReference<>(0);
        // 如果是编辑调用的添加需要获得当前数据库的最大值
        if (isExcludeSelf) {
            String saleCode = saleOrder.getCode() + "-";
            QueryWrapper<WorkOrder> WorkCodeQW = new QueryWrapper<>();
            WorkCodeQW.lambda().like(WorkOrder::getWorkOrderNo, saleCode);
            List<WorkOrder> workOrders = workOrderService.list(WorkCodeQW);
            List<Integer> numberInt = new ArrayList<>();
            workOrders.forEach(workOrder -> numberInt.add(Integer.valueOf(StrUtil.sub(workOrder.getWorkOrderNo(), saleCode.length(), workOrder.getWorkOrderNo().length()))));

            // 查询数据库中编码最大值
            if (ObjectUtil.isNotEmpty(numberInt)) {
                Integer maxNumber = Collections.max(numberInt);
                workOrderNumber.set(workOrderNumber.get() + maxNumber);
            }
        }
        // 工单中产品类型需要
        List<Pro> proList = proService.list();
        Map<Long, Pro> proMap = proList.stream().collect(Collectors.toMap(Pro::getId, a -> a, (k1, k2) -> k1));
        // 批量添加工单开始 因为要用到所有 所以不用 forEach
        for (int i = 0; i < addWorkOrderList.size(); i++) {
            addWorkOrderList.get(i).setType(WorkOrderTypeEnum.SEQUENTIAL_WORK_ORDER.getCode());
            addWorkOrderList.get(i).setWorkOrderNo(StrUtil.format(template, saleOrder.getCode(), workOrderNumber.get() + 1));
            workOrderNumber.set(workOrderNumber.get() + 1);
            addWorkOrderList.get(i).setProTypeId(proMap.get(addWorkOrderList.get(i).getProId()).getProTypeId());
            addWorkOrderList.get(i).setBillId(addWorkOrderBillList.get(i).getId());
            addWorkOrderList.get(i).setStatus(WorkOrderStatusEnum.NOT_START.getCode());
            addWorkOrderList.get(i).setNextPerson(LoginContextHolder.me().getSysLoginUserId());
            addWorkOrderList.get(i).setPersonCharge(LoginContextHolder.me().getSysLoginUserId());
            addWorkOrderList.get(i).setOrderTime(new Date());
        }
        // 批量添加工单
        workOrderService.saveBatch(addWorkOrderList);
        // 批量添加任务开始
        // 设置一个addTaskList 为批量增加工单做准备
        List<Task> addTaskList = new ArrayList<>();
        // 获取工艺路线与工序关系，并且进行排序
        QueryWrapper<WorkStepRoute> workStepRouteQueryWrapper = new QueryWrapper<>();
        //升序
        workStepRouteQueryWrapper.lambda().orderByAsc(WorkStepRoute::getSortNum);
        List<WorkStepRoute> workStepRouteList = workStepRouteService.list(workStepRouteQueryWrapper);
        // 设定一个Map key 为工艺路线id,value 为 该工艺路线下的所有 工序工艺路线关系
        Map<Long, List<WorkStepRoute>> workStepRoutMap = workStepRouteList.stream().collect(Collectors.groupingBy(WorkStepRoute::getWorkRouteId));
        // 设定一个Map key 为工序工艺路线关系id,value 为 所对应的工序
        List<WorkStep> workStepList = workStepService.list();
        Map<Long, WorkStep> workStepMap = workStepList.stream().collect(Collectors.toMap(WorkStep::getId, a -> a, (k1, k2) -> k1));
        // 开始添加
        addWorkOrderList.forEach(workOrder -> {
            if(ObjectUtil.isNull(workStepRoutMap)||ObjectUtil.isNull(proMap.get(workOrder.getProId()).getWorkRouteId())){
                throw new ServiceException(10,"请添加工艺路线");
            }
            workStepRoutMap.get(proMap.get(workOrder.getProId()).getWorkRouteId()).forEach(workStepRoute -> {
            Task task = new Task();
            task.setSortNum(workStepRoute.getSortNum());
            task.setWorkOrderId(workOrder.getId());
            task.setProId(workOrder.getProId());
            task.setProTypeId(workOrder.getProTypeId());
            task.setWorkStepId(workStepRoute.getWorkStepId());
            task.setPlaNum(workOrder.getPlaNum());
            task.setPlaStartTime(workOrder.getPlaStartTime());
            task.setPlaEndTime(workOrder.getPlaEndTime());
            task.setStatus(TaskStatusEnum.NOT_START.getCode());
            task.setReportRight(workStepMap.get(workStepRoute.getWorkStepId()).getReportRight());
            task.setGoodNum(0);
            task.setBadNum(0);
            addTaskList.add(task);
            });
        });
        List<String> taskCodes = AutoCode.getCodeByService("dw_task", this.getClass(), "code", addTaskList.size());
        for (int i = 0; i < taskCodes.size(); i++) {
            addTaskList.get(i).setCode(taskCodes.get(i));
        }
        // 添加任务完成
        taskService.saveBatch(addTaskList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<SaleOrderParam> saleOrderParamList) {
        // 查找所有销售订单关系
        QueryWrapper<WorkOrderBill> workOrderBillQW = new QueryWrapper<>();
        workOrderBillQW.lambda().eq(WorkOrderBill::getType, WorkOrderBillEnum.ProPlan.getCode());
        List<WorkOrderBill> billList = workOrderBillService.list();
        //map  key:销售订单id   value：销售订单关系列表
        Map<Long, List<WorkOrderBill>> billGroupByInvId = billList.stream().collect(Collectors.groupingBy(WorkOrderBill::getBillId));
        //map  key:关联单据id   value：工单
        List<WorkOrder> workOrderList = workOrderService.list();
        Map<Long, WorkOrder> workOrderMap = workOrderList.stream().collect(Collectors.toMap(WorkOrder::getBillId, a -> a, (k1, k2) -> k1));
        // 记录删除销售订单的条件
        QueryWrapper<SaleOrder> proPlanQueryWrapper = new QueryWrapper<>();
        // 记录删除工单单据关系的条件
        QueryWrapper<WorkOrderBill> workOrderBillQueryWrapper = new QueryWrapper<>();
        // 记录删除工单的条件
        QueryWrapper<WorkOrder> workOrderQueryWrapper = new QueryWrapper<>();
        // 记录删除任务的条件
        QueryWrapper<Task> taskQueryWrapper = new QueryWrapper<>();
        // 记录删除报工的条件
        QueryWrapper<WorkReport> workReportQueryWrapper = new QueryWrapper<>();
        saleOrderParamList.forEach((saleOrderParam) -> {
            // 根据工单单据详情查找相应的工单
            if (ObjectUtils.isNotEmpty(billGroupByInvId.get(saleOrderParam.getId()))) {
                billGroupByInvId.get(saleOrderParam.getId()).forEach(item -> {
                    // 记录删除工单的条件
                    workOrderQueryWrapper.lambda().eq(WorkOrder::getBillId, item.getId()).or();
                    WorkOrder workOrder = workOrderMap.get(item.getId());
                    // 记录删除任务的条件
                    taskQueryWrapper.lambda().eq(Task::getWorkOrderId, workOrder.getId()).or();
                    // 记录删除报工的条件
                    workReportQueryWrapper.lambda().eq(WorkReport::getWorkOrderId, workOrder.getId()).or();
                });
            }
            // 记录删除工单单据关系的条件
            workOrderBillQueryWrapper.lambda().eq(WorkOrderBill::getBillId, saleOrderParam.getId()).or();
            // 记录删除销售订单的条件
            proPlanQueryWrapper.lambda().eq(SaleOrder::getId, saleOrderParam.getId()).or();
        });
        // 删除报工
        workReportService.remove(workReportQueryWrapper);
        // 删除任务
        taskService.remove(taskQueryWrapper);
        // 删除工单
        workOrderService.remove(workOrderQueryWrapper);
        // 删除工单单据关系
        workOrderBillService.remove(workOrderBillQueryWrapper);
        // 删除装配工单
        this.remove(proPlanQueryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SaleOrderParam saleOrderParam) {
        checkParam(saleOrderParam,true);
        SaleOrder saleOrder = this.querySaleOrder(saleOrderParam);
        BeanUtil.copyProperties(saleOrderParam, saleOrder);
        this.updateById(saleOrder);
        //如果编码为空，手动添加编码
        if (ObjectUtil.isEmpty(saleOrderParam.getCode())) {
            throw new ServiceException(10, "编号不能为空，请输入编号");
        }
        //该销售订单id
        Long saleOrderId = saleOrder.getId();
        //需要添加的新的工单
        List<WorkOrder> addWorkOrderList = new ArrayList<>();
        //需要删除的工单的id
        List<Long> deleteWorkOrderIdList = new ArrayList<>();
        //需要编辑的工单
        List<WorkOrder> editWorkOrderList = new ArrayList<>();
        //查找该销售订单下的工单关系条件
        QueryWrapper<WorkOrderBill> workOrderBillQueryWrapper = new QueryWrapper<>();
        workOrderBillQueryWrapper.lambda().eq(WorkOrderBill::getBillId, saleOrderId);
        //获取该销售订单下所有的工单关系
        List<WorkOrderBill> workOrderBills = workOrderBillService.list(workOrderBillQueryWrapper);
        //查找对应的工单
        QueryWrapper<WorkOrder> workOrderQueryWrapper = new QueryWrapper<>();
        workOrderBills.forEach(workOrderBill -> workOrderQueryWrapper.lambda().eq(WorkOrder::getBillId, workOrderBill.getId()).or());
        List<WorkOrder> oldWorkOrderList = workOrderService.list(workOrderQueryWrapper);
        oldWorkOrderList.forEach(workOrder -> {
            //将原来的工单id添加至删除列表中
            deleteWorkOrderIdList.add(workOrder.getId());
        });
        //遍历前端传来的所有的
        saleOrderParam.getWorkOrderList().forEach(workOrder -> {
            //若id为空则需要新增
            if (ObjectUtil.isEmpty(workOrder.getId())) {
                addWorkOrderList.add(workOrder);
            } else if (ObjectUtil.isNotEmpty(workOrder.getId())) {
                //需要修改的工单
                editWorkOrderList.add(workOrder);
                //从删除列表里移除
                deleteWorkOrderIdList.remove(workOrder.getId());
            }
        });
        //查找所有工单
        List<WorkOrder> workOrders = workOrderService.list();
        //将工单与工单单据id对应的map
        Map<Long, WorkOrder> workOrderMap = workOrders.stream().collect(Collectors.toMap(WorkOrder::getId, a -> a, (k1, k2) -> k1));
//        //查找所有任务
//        List<Task> tasks=taskService.list();
//        //key:工单id value:任务list
//        Map<Long,List<Task>> taskMap=tasks.stream().collect(Collectors.groupingBy(Task::getWorkOrderId));
        // 设定一个Map key 为工单id,value 为 该工单的所有报工
        List<WorkReport> workReportList = workReportService.list();
        Map<Long, List<WorkReport>> workReporMap = workReportList.stream().collect(Collectors.groupingBy(WorkReport::getWorkOrderId));
        // 设定一个删除任务的 deleteTaskListQW
        QueryWrapper<Task> deleteTaskListQW = new QueryWrapper<>();
        // 设定一个删除报工的 deleteWorkReportQW
        QueryWrapper<WorkReport> deleteWorkReportQW = new QueryWrapper<>();
        //需要新增的任务
        List<Task> addTaskList = new ArrayList<>();
        // 获取工艺路线与工序关系，并且进行排序
        QueryWrapper<WorkStepRoute> workStepRouteQueryWrapper = new QueryWrapper<>();
        //升序
        workStepRouteQueryWrapper.lambda().orderByAsc(WorkStepRoute::getSortNum);
        List<WorkStepRoute> workStepRouteList = workStepRouteService.list(workStepRouteQueryWrapper);
        // 设定一个Map key 为工艺路线id,value 为 该工艺路线下的所有 工序工艺路线关系
        Map<Long, List<WorkStepRoute>> workStepRoutMap = workStepRouteList.stream().collect(Collectors.groupingBy(WorkStepRoute::getWorkRouteId));
        // 设定一个Map key 为工序工艺路线关系id,value 为 所对应的工序
        List<WorkStep> workStepList = workStepService.list();
        Map<Long, WorkStep> workStepMap = workStepList.stream().collect(Collectors.toMap(WorkStep::getId, a -> a, (k1, k2) -> k1));
        // 工单中产品类型需要
        List<Pro> proList = proService.list();
        Map<Long, Pro> proMap = proList.stream().collect(Collectors.toMap(Pro::getId, a -> a, (k1, k2) -> k1));
        AtomicBoolean flag = new AtomicBoolean(false);
        editWorkOrderList.forEach(workOrder -> {
            // 判断产品是否发生变化
            if (!workOrder.getProId().equals(workOrderMap.get(workOrder.getId()).getProId()) && ObjectUtil.isNotEmpty(workOrderMap.get(workOrder.getId()).getProId())) {
                // 产品变了，就删除原先的所有任务
                deleteTaskListQW.lambda().eq(Task::getWorkOrderId, workOrder.getId()).or();
                flag.set(true);
                // 产品变了，就删除原先的所有报工
                if (ObjectUtil.isNotEmpty(workReporMap.get(workOrder.getId()))) {
                    deleteWorkReportQW.lambda().eq(WorkReport::getWorkOrderId, workOrder.getId()).or();
                }
                // 添加任务
                workStepRoutMap.get(proMap.get(workOrder.getProId()).getWorkRouteId()).forEach(workStepRoute -> {
                    Task task = new Task();
                    task.setSortNum(workStepRoute.getSortNum());
                    task.setWorkOrderId(workOrder.getId());
                    task.setProId(workOrder.getProId());
                    task.setProTypeId(workOrder.getProTypeId());
                    task.setWorkStepId(workStepRoute.getWorkStepId());
                    task.setPlaNum(workOrder.getPlaNum());
                    task.setPlaStartTime(workOrder.getPlaStartTime());
                    task.setPlaEndTime(workOrder.getPlaEndTime());
                    task.setStatus(TaskStatusEnum.NOT_START.getCode());
                    task.setReportRight(workStepMap.get(workStepRoute.getWorkStepId()).getReportRight());
                    task.setGoodNum(0);
                    task.setBadNum(0);
                    addTaskList.add(task);
                });
                List<String> taskCodes = AutoCode.getCodeByService("dw_task", this.getClass(), "code", addTaskList.size());
                for (int i = 0; i < taskCodes.size(); i++) {
                    addTaskList.get(i).setCode(taskCodes.get(i));
                }
            }
        });
        // 删除任务
        if (flag.get()) {
            taskService.remove(deleteTaskListQW);
        }
        // 添加任务
        if (ObjectUtil.isNotEmpty(addTaskList)) {
            taskService.saveBatch(addTaskList);
        }
        // 删除报工
        workReportService.remove(deleteWorkReportQW);
        if (ObjectUtil.isNotEmpty(editWorkOrderList)) {
            workOrderService.updateBatchById(editWorkOrderList);
        }
        // 添加
        if (ObjectUtil.isNotEmpty(addWorkOrderList)) {
            addOrUpdateWrok(saleOrder, addWorkOrderList, true);
        }
        // 删除
        if (ObjectUtil.isNotEmpty(deleteWorkOrderIdList)) {
            updateDelete(deleteWorkOrderIdList);
        }
        //查询编辑完后销售订单的工单列表是否为空
        QueryWrapper<WorkOrderBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WorkOrderBill::getBillId,saleOrder.getId());
        List<WorkOrderBill> list=workOrderBillService.list(queryWrapper);
        //为空则删除该条销售订单
        if (ObjectUtil.isEmpty(list)){
            this.removeById(saleOrder.getId());
        }
    }

    private void updateDelete(List<Long> deleteWorkOrderIdList) {
        // 设定一个Map key 为工单id,value 为 工单
        List<WorkOrder> workOrderList = workOrderService.list();
        Map<Long, WorkOrder> workOrderMap = workOrderList.stream().collect(Collectors.toMap(WorkOrder::getId, a -> a, (k1, k2) -> k1));
        // 需要被删除任务的条件
        QueryWrapper<Task> taskQueryWrapper = new QueryWrapper<>();
        // 需要被删除报工的条件
        QueryWrapper<WorkReport> workReportQueryWrapper = new QueryWrapper<>();
        List<Task> taskList = taskService.list();
        Map<Long, List<Task>> longListMap = taskList.stream().collect(Collectors.groupingBy(Task::getWorkOrderId));
        List<Long> deleteTaskList = new ArrayList<>();
        // 需要被删除工单单据关系的条件
        List<Long> workOrderBillId = new ArrayList<>();
        deleteWorkOrderIdList.forEach(workOrderId -> {
            // 添加需要删除的任务
            workReportQueryWrapper.lambda().eq(WorkReport::getWorkOrderId, workOrderId).or();
            // 添加需要删除的报工
            taskQueryWrapper.lambda().eq(Task::getWorkOrderId, workOrderId);
            if (ObjectUtil.isNotEmpty(longListMap.get(workOrderId))){
                longListMap.get(workOrderId).forEach(task -> deleteTaskList.add(task.getId()));

            }
            // 添加需要删除的工单关系
            workOrderBillId.add(workOrderMap.get(workOrderId).getBillId());
        });
        // 删除报工
        workReportService.remove(workReportQueryWrapper);
        // 删除任务
        taskService.removeByIds(deleteTaskList);
        // 删除工单
        workOrderService.removeByIds(deleteWorkOrderIdList);
        // 删除工单单据关系
        workOrderBillService.removeByIds(workOrderBillId);
    }

    @Override
    public SaleOrder detail(SaleOrderParam saleOrderParam) {
        return this.querySaleOrder(saleOrderParam);
    }

    /**
     * 获取销售订单
     *
     * @author wyf
     * @date 2022-07-12 16:07:31
     */
    private SaleOrder querySaleOrder(SaleOrderParam saleOrderParam) {
        SaleOrder saleOrder = this.getById(saleOrderParam.getId());
        if (ObjectUtil.isNull(saleOrder)) {
            throw new ServiceException(SaleOrderExceptionEnum.NOT_EXIST);
        }
        return saleOrder;
    }

    @Override
    public void export(SaleOrderParam saleOrderParam) {
        List<SaleOrder> list = this.list(saleOrderParam);
        PoiUtil.exportExcelWithStream("SnowySaleOrder.xls", SaleOrder.class, list);
    }

    private void checkParam(SaleOrderParam saleOrderParam, boolean isExcludeSelf) {
        if(ObjectUtil.isEmpty(saleOrderParam.getWorkOrderList())){
            throw new ServiceException(12,"工单列表不能为空");
        }
        //校验数据是否为空
        for (WorkOrder workOrder : saleOrderParam.getWorkOrderList()) {
            if (ObjectUtil.isEmpty(workOrder.getProId())) {
                throw new ServiceException(3, "产品不能为空，请添加产品");
            }
            if (ObjectUtil.isEmpty(workOrder.getPlaNum()) || workOrder.getPlaNum() <= 0) {
                throw new ServiceException(4, "产品数量不能为空并且必须大于零，请重新输入");
            }
        }
        LambdaQueryWrapper<SaleOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //如果是编辑需要去除自己
        if (isExcludeSelf) {
            lambdaQueryWrapper.ne(SaleOrder::getId, saleOrderParam.getId());
        }
        lambdaQueryWrapper.eq(SaleOrder::getCode, saleOrderParam.getCode());
        int count = this.count(lambdaQueryWrapper);
        if (count >= 1) {
            throw new ServiceException(2, "唯一编号已存在");
        }


    }

}